package com.sheng.leetcode.year2023.month02.day13;

import org.junit.Test;

/**
 * @author liusheng
 * @date 2023/02/13
 * <p>
 * 1234. 替换子串得到平衡字符串<p>
 * <p>
 * 有一个只含有 'Q', 'W', 'E', 'R' 四种字符，且长度为 n 的字符串。<p>
 * 假如在该字符串中，这四个字符都恰好出现 n/4 次，那么它就是一个「平衡字符串」。<p>
 * 给你一个这样的字符串 s，请通过「替换一个子串」的方式，使原字符串 s 变成一个「平衡字符串」。<p>
 * 你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。<p>
 * 请返回待替换子串的最小可能长度。<p>
 * 如果原字符串自身就是一个平衡字符串，则返回 0。<p>
 * <p>
 * 示例 1：<p>
 * 输入：s = "QWER"<p>
 * 输出：0<p>
 * 解释：s 已经是平衡的了。<p>
 * <p>
 * 示例 2：<p>
 * 输入：s = "QQWE"<p>
 * 输出：1<p>
 * 解释：我们需要把一个 'Q' 替换成 'R'，这样得到的 "RQWE" (或 "QRWE") 是平衡的。<p>
 * <p>
 * 示例 3：<p>
 * 输入：s = "QQQW"<p>
 * 输出：2<p>
 * 解释：我们可以把前面的 "QQ" 替换成 "ER"。<p>
 * <p>
 * 示例 4：<p>
 * 输入：s = "QQQQ"<p>
 * 输出：3<p>
 * 解释：我们可以替换后 3 个 'Q'，使 s = "QWER"。<p>
 * <p>
 * 提示：<p>
 * 1 <= s.length <= 10^5<p>
 * s.length 是 4 的倍数<p>
 * s 中只含有 'Q', 'W', 'E', 'R' 四种字符<p>
 * <p>
 * 来源：力扣（LeetCode）<p>
 * 链接：<a href="https://leetcode.cn/problems/replace-the-substring-for-balanced-string">1234. 替换子串得到平衡字符串</a><p>
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。<p>
 */
public class LeetCode1234 {

    @Test
    public void test01() {
        String s = "QWER";
//        String s = "QQWE";
//        String s = "QQQW";
//        String s = "QQQQ";
        System.out.println(new Solution().balancedString(s));
    }
}

class Solution {
    public int balancedString(String s) {
        String str = "QWER";
        int[] nums = new int[4];
        // 循环计算字符串 s 中每个字符的数量
        for (int i = 0; i < s.length(); i++) {
            nums[str.indexOf(s.charAt(i))]++;
        }
        int n = s.length();
        int m = n / 4;
        // 判断当前字符串是否满足平衡字符串
        if (nums[0] == m && nums[1] == m && nums[2] == m && nums[3] == m) {
            // 满足则返回 0
            return 0;
        }
        // ans 代表需要替换的子串的长度
        int ans = n;
        // 双指针 j 和 i 分别维护左，右边界，从左到右遍历字符串 s，初始时 j = 0
        for (int i = 0, j = 0; i < n; i++) {
            // 将 i 位置的字符数量减去
            nums[str.indexOf(s.charAt(i))]--;
            // 判断当前是否满足条件
            while (j <= i && nums[0] <= m && nums[1] <= m && nums[2] <= m && nums[3] <= m) {
                // 满足条件，更新 ans，然后将窗口的左边界右移直到不满足条件为止
                ans = Math.min(ans, i - j + 1);
                nums[str.indexOf(s.charAt(j++))]++;
            }
        }
        return ans;
    }
}
